const {
	Service
} = require('uni-cloud-router')
const uniID = require('uni-id')
const dbHelper = require('db-helper')
const payUtil = require("pay-util")
const {
	wxPubConfig
} = require("config");
const WxPubApi = require("wx-public-api")
const wxPubApi = new WxPubApi()
const moment = require('moment-timezone');
const fs = require('fs');
const path = require('path');
const {
	WxWithdraw
} = require('node-wxpay3');
const wxwithdeaw = new WxWithdraw({
	'partner_key': '409fd902fec330f320662a45d1d97c8f', // key为商户平台设置的密钥key
	'pfx': fs.readFileSync(path.join(__dirname, "../apiclient_cert.p12")),
});
const {
	v1: uuidv1
} = require('uuid');

module.exports = class TradeService extends Service {
	async getIncomeDetail({
		startDate,
		endDate,
		pageNum = 1,
		pageSize = 20,
		userId,
		tradeType
	}) {
		let dbCmd = this.db.command
		try {
			let result = {
				totalFee: 0,
				page: {
					total: 0,
					list: []
				}
			}
			let query = {
				userId: userId
			}

			if (tradeType) {
				query.tradeType = tradeType
			} else {
				query.tradeType = dbCmd.in([5, 9, 12])
			}
			if (startDate && endDate) {
				query.createTime = dbCmd.gte(startDate).and(dbCmd.lte(endDate));
			} else if (startDate) {
				query.createTime = dbCmd.gte(startDate);
			} else if (endDate) {
				query.createTime = dbCmd.lte(endDate);
			}
			let $ = dbCmd.aggregate;
			console.log("query: ", query);
			let totalIncomeRes = await this.db.collection("t3ds-account-log").aggregate()
				.match(query)
				.group({
					_id: null,
					total: $.sum('$income')
				})
				.end();
			console.log("totalIncomeRes: ", totalIncomeRes.data);
			if (totalIncomeRes.data.length) {
				result.totalFee = totalIncomeRes.data[0].total;
			}
			if (tradeType == 5) {
				let count = await dbHelper.getCount("t3ds-account-log", query)
				if (count) {
					result.page.total = count
					let res = await this.db.collection("t3ds-account-log").aggregate()
						.match(query)
						.lookup({
							from: "t3ds-ticket-code",
							localField: "ticketCodeId",
							foreignField: "_id",
							as: "ticket"
						})
						.unwind("$ticket")
						.sort({
							"ticket.chargeoffTime": -1
						})
						.skip((pageNum - 1) * pageSize)
						.limit(pageSize)
						.lookup({
							from: "t3ds-order",
							localField: "orderId",
							foreignField: "_id",
							as: "order"
						})
						.unwind("$order")
						.lookup({
							from: "uni-id-users",
							localField: "order.user_id",
							foreignField: "_id",
							as: "member"
						})
						.unwind("$member")
						.project({
							income: "$income",
							tradeType: "$tradeType",
							goodsName: "$ticket.goodsName",
							goodsPrice: "$ticket.goodsPrice",
							chargeoffTime: "$ticket.chargeoffTime",
							employeeName: "$ticket.employeeName",
							storeName: "$ticket.storeName",
							ticketSource: "$ticket.source",
							buyMan: "$member.user_nickname",
							buyManId: "$member.id",
							skuName: "$order.items.sku_name"
						})
						.unwind("$skuName")
						.end()
					res.data.forEach(item => {
						item.income = Math.round(item.income)
						item.goodsPrice = Math.round(item.goodsPrice)
					})
					result.page.list = res.data
				}
			} else if (tradeType == 9) {
				let count = await dbHelper.getCount("t3ds-account-log", query)
				if (count) {
					result.page.total = count
					let res = await this.db.collection("t3ds-account-log").aggregate()
						.match(query)
						.lookup({
							from: "t3ds-vip-chargeoff-record",
							localField: "vipEnterId",
							foreignField: "_id",
							as: "records"
						})
						.sort({
							'records.enterInfo.time': -1
						})
						.skip((pageNum - 1) * pageSize)
						.limit(pageSize)
						.end()
					res.data.forEach(item => {
						item.income = Math.round(item.income)
						let record = records[0]
						item.enterTime = record.enterInfo.time
						if (record.outInfo) {
							item.outTime = record.outInfo.time
							item.stayTimes = item.outTime - item.enterTime
						}
						item.member = record.memberNickname
						item.storeName = record.storeName
					})
					result.page.list = res.data
				}
			} else {
				let page = await dbHelper.getPage("t3ds-account-log", pageNum, pageSize, query, [{
					field: "createTime",
					order: "desc"
				}]);
				if (page.list.length) {
					for (var i = 0; i < page.list.length; i++) {
						let item = page.list[i];
						if (item.ticketCodeId) {
							let ticketCode = await dbHelper.getById("t3ds-ticket-code", item.ticketCodeId);
							item.goodsName = ticketCode.goodsName;
							item.goodsPrice = ticketCode.goodsPrice;
							item.chargeoffTime = ticketCode.chargeoffTime;
							item.employeeName = ticketCode.employeeName;
							item.storeName = ticketCode.storeName
							item.ticketSource = ticketCode.source
						}
						if (item.orderId) {
							let order = await dbHelper.getById("t3ds-order", item.orderId);
							let member = await dbHelper.getById("uni-id-users", order.user_id)
							item.buyMan = order.user_nickname;
							item.buyManId = member.id
							item.goodsName = order.items[0].goods_name
							item.skuName = order.items[0].sku_name;
						}
						if (item.tradeType === 9 && item.vipEnterId) {
							let record = await dbHelper.getById("t3ds-vip-chargeoff-record", item.vipEnterId)
							item.enterTime = record.enterInfo.time
							if (record.outInfo) {
								item.outTime = record.outInfo.time
								item.stayTimes = item.outTime - item.enterTime
							}
							item.member = record.memberNickname
							item.storeName = record.storeName
						}

						if (item.tradeType === -3 && item.refundApplyId) {
							let refundApply = await dbHelper.getById("t3ds-refund-apply", item.refundApplyId)
							item.damages = refundApply.damages
							item.refundReason = refundApply.reason
							item.refundTime = refundApply.auditTime
						}

						if (item.tradeType == 12 && item.motorcadeId) {
							console.log("motorcadeId: ", item.motorcadeId);
							let motorcade = await dbHelper.getById("t3ds-subscribe-motorcade", item.motorcadeId)
							if (motorcade) {
								item.motorcadeName = motorcade.name
								item.startWorkTime = motorcade.startWorkTime
								item.finishWorkTime = motorcade.finishWorkTime
								item.playerCount = motorcade.currentMaleCount + motorcade.currentFemaleCount
							}
						}
					}
				}
				result.page = page;
			}

			return {
				code: 200,
				result: result
			}
		} catch (e) {
			console.log("获取收益明细遇到错误", e);
			return {
				code: 500,
				msg: e.message
			}
		}
	}

	async getWithdrawList({
		pageNum = 1,
		pageSize = 10,
		userId,
		isMember = true
	}) {
		let result = {
			total: 0,
			list: []
		}
		let query = {
			isMember
		}
		if (userId) {
			query.userId = userId
		}
		const dbCmd = this.db.command
		const $ = dbCmd.aggregate
		if (pageNum == 1) {
			let totalRes = await this.db.collection("t3ds-withdraw-apply")
				.where(query)
				.count()
			result.total = totalRes.total
			if (!result.total) {
				return result
			}
		}
		let res = await this.db.collection("t3ds-withdraw-apply")
			.aggregate()
			.match(query)
			.sort({
				createTime: -1
			})
			.skip((pageNum - 1) * pageSize)
			.limit(pageSize)
			.lookup({
				from: "uni-id-users",
				foreignField: "_id",
				localField: "userId",
				as: "users"
			})
			.lookup({
				from: "t3ds-account",
				foreignField: "userId",
				localField: "userId",
				as: "accounts"
			})
			.project({
				status: 1,
				isMember: 1,
				createTime: 1,
				auditTime: 1,
				fee: 1,
				user: $.arrayElemAt(['$users', 0]),
				account: $.arrayElemAt(['$accounts', 0])
			})
			.project({
				status: 1,
				isMember: 1,
				createTime: 1,
				auditTime: 1,
				fee: 1,
				nickname: '$user.nickname',
				username: '$user.username',
				merchantInfo: '$user.merchant_info',
				id: '$user.id',
				balance: '$account.balance'
			})
			.end()
		result.list = res.data
		return result
	}

	async auditWithdrawApply(applyId, action, note) {
		let transaction
		try {
			let user = await dbHelper.getById("uni-id-users", this.ctx.auth.uid)
			if (!user.role.some(role => {
					return role === 'admin'
				})) {
				return {
					code: 500,
					msg: '无权限'
				}
			}
			let apply = await dbHelper.getById("t3ds-withdraw-apply", applyId);
			if (!apply) {
				return {
					code: 500,
					msg: "记录不存在"
				}
			}
			if (apply.status !== "WAITING") {
				return {
					code: 500,
					msg: "已审核，不能再次审核"
				}
			}
			transaction = await this.db.startTransaction();

			let openId, unionId, targetUserId;
			let applyUser = await dbHelper.getById("uni-id-users", apply.userId)
			let account = await dbHelper.getOne("t3ds-account", {
				userId: applyUser._id
			})
			if (action === "PASSED") {
				
				// 判断是否是头条用户
				if(applyUser.tt_unionid){
					if(apply.isMember&&applyUser.wx_openid["mp-weixin-gzh"]){
						return {
							code: 500,
							msg: "用户还没绑定微信，不能提现"
						}
					}
				}else{
					if ((apply.isMember && (!applyUser.wx_openid || (!applyUser.wx_openid["mp-weixin"])) ||
						!apply.isMember && (!applyUser.merchant_info || !applyUser.merchant_info.wx_openid || !
							applyUser.merchant_info.wx_openid["mp-weixin"]))) {
						return {
							code: 500,
							msg: "用户还没绑定微信，不能提现"
						}
					}
				}
				account.frozen -= apply.fee;
				account.total -= apply.fee;
				await dbHelper.update("t3ds-account", account, transaction);
			} else {
				account.frozen -= apply.fee;
				account.balance += apply.fee;
				await dbHelper.update("t3ds-account", account, transaction);
			}

			let accountLog = {
				accountId: account._id,
				userId: applyUser._id,
				total: account.total,
				balance: account.balance,
				settle: account.settle,
				frozen: account.frozen,
				income: apply.fee,
				tradeType: -2,
				settled: true,
				createTime: Date.now(),
				createBy: user.nickname
			}
			await transaction.collection("t3ds-account-log").add(accountLog);

			apply.status = action;
			apply.auditBy = user.username;
			apply.auditTime = Date.now();
			apply.note = note;
			let tradeNo = uuidv1().replace(/-/g, '');
			apply.tradeNo = tradeNo;
			await dbHelper.update("t3ds-withdraw-apply", apply, transaction);

			if (action === "PASSED") {
				//打款到微信零钱
				let options={
					'mch_appid': apply.isMember ? 'wx609a0a547e98415d' : 'wxa7e5444036dea6af',
					'mchid': '1529710361',
					'partner_trade_no': apply.tradeNo,
					'openid': apply.isMember ? applyUser.wx_openid['mp-weixin-gzh'] : applyUser.merchant_info
						.wx_openid["mp-weixin-gzh"],
					'check_name': 'NO_CHECK',
					'amount': apply.fee,
					'desc': '用户提现'
				};
				if(applyUser.tt_unionid){
					options.openid=applyUser.merchant_info.wx_openid["mp-weixin-gzh"]
				}else{
					options.openid=apply.isMember ? applyUser.wx_openid['mp-weixin'] : applyUser.merchant_info.wx_openid["mp-weixin"]
				}
				const result = await wxwithdeaw.transfers(options);
				console.log("提现结果", result);
				if (result.result_code !== "SUCCESS") {
					await transaction.rollback();
					return {
						code: 500,
						msg: result.err_code_des
					}
				}
			}
			await transaction.commit();
			//发送通知
			try {
				let unionId = apply.isMember ? applyUser.wx_unionid : applyUser.merchant_info.wx_unionid
				if (unionId) {
					let wxPubUser = await dbHelper.getOne("t3ds-wx-pub-user", {
						unionId: unionId,
						city: applyUser.city
					})
					if (wxPubUser) {
						let temp = await dbHelper.getOne('t3ds-region', {
							'city.value': applyUser.city
						})
						let tempId = temp.templateMsgs.find(item => {
							return item.templateName === '提现结果通知'
						}).templateID
						await wxPubApi.sendTemplateMsg(applyUser.city, {
							touser: wxPubUser.openId,
							template_id: tempId,
							data: {
								first: {
									value: action === "PASSED" ? "您的提现申请已通过，请留言微信打款通知！" : "您的提现申请未通过！"
								},
								keyword1: {
									value: "第三空间"
								},
								keyword2: {
									value: (apply.fee / 100).toFixed(2)
								},
								keyword3: {
									value: '微信零钱'
								},
								keyword4: {
									value: moment().tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss")
								},
								remark: {
									value: action === "PASSED" ? "感谢使用！" : apply.note
								}
							}
						})
					} else {
						console.log("用户没有关注公众号，无法发送通知")
					}
				} else {
					console.log("用户没有unionId，无法发送通知")
				}
			} catch (e) {
				console.error("发送通知遇到错误", e);
			}

			return {
				code: 200,
				result: {
					...apply,
					...account
				}
			}
		} catch (e) {
			console.log("审核遇到错误，事务回滚", e);
			if (transaction) {
				await transaction.rollback();
			}
			return {
				code: 500,
				msg: e.message
			}
		}
	}
	
	async auditManualWithdrawApply(applyId, action, note) {
		let transaction
		try {
			let user = await dbHelper.getById("uni-id-users", this.ctx.auth.uid)
			if (!user.role.some(role => {
					return role === 'admin'
				})) {
				return {
					code: 500,
					msg: '无权限'
				}
			}
			let apply = await dbHelper.getById("t3ds-withdraw-apply", applyId);
			if (!apply) {
				return {
					code: 500,
					msg: "记录不存在"
				}
			}
			if (apply.status !== "WAITING") {
				return {
					code: 500,
					msg: "已审核，不能再次审核"
				}
			}
			transaction = await this.db.startTransaction();
	
			let openId, unionId, targetUserId;
			let applyUser = await dbHelper.getById("uni-id-users", apply.userId)
			let account = await dbHelper.getOne("t3ds-account", {
				userId: applyUser._id
			})
			if (action === "PASSED") {
				
				// 判断是否是头条用户
				if(applyUser.tt_unionid){
					if(apply.isMember&&applyUser.wx_openid["mp-weixin-gzh"]){
						return {
							code: 500,
							msg: "用户还没绑定微信，不能提现"
						}
					}
				}else{
					if ((apply.isMember && (!applyUser.wx_openid || (!applyUser.wx_openid["mp-weixin"])) ||
						!apply.isMember && (!applyUser.merchant_info || !applyUser.merchant_info.wx_openid || !
							applyUser.merchant_info.wx_openid["mp-weixin"]))) {
						return {
							code: 500,
							msg: "用户还没绑定微信，不能提现"
						}
					}
				}
				account.frozen -= apply.fee;
				account.total -= apply.fee;
				await dbHelper.update("t3ds-account", account, transaction);
			} else {
				account.frozen -= apply.fee;
				account.balance += apply.fee;
				await dbHelper.update("t3ds-account", account, transaction);
			}
	
			let accountLog = {
				accountId: account._id,
				userId: applyUser._id,
				total: account.total,
				balance: account.balance,
				settle: account.settle,
				frozen: account.frozen,
				income: apply.fee,
				tradeType: -2,
				settled: true,
				createTime: Date.now(),
				createBy: user.nickname
			}
			await transaction.collection("t3ds-account-log").add(accountLog);
	
			apply.status = action;
			apply.auditBy = user.username;
			apply.auditTime = Date.now();
			apply.note = note;
			let tradeNo = uuidv1().replace(/-/g, '');
			apply.tradeNo = tradeNo;
			await dbHelper.update("t3ds-withdraw-apply", apply, transaction);
	
			await transaction.commit();
			//发送通知
			try {
				let unionId = apply.isMember ? applyUser.wx_unionid : applyUser.merchant_info.wx_unionid
				if (unionId) {
					let wxPubUser = await dbHelper.getOne("t3ds-wx-pub-user", {
						unionId: unionId,
						city: applyUser.city
					})
					if (wxPubUser) {
						let temp = await dbHelper.getOne('t3ds-region', {
							'city.value': applyUser.city
						})
						let tempId = temp.templateMsgs.find(item => {
							return item.templateName === '提现结果通知'
						}).templateID
						await wxPubApi.sendTemplateMsg(applyUser.city, {
							touser: wxPubUser.openId,
							template_id: tempId,
							data: {
								first: {
									value: action === "PASSED" ? "您的提现申请已通过，请留言微信打款通知！" : "您的提现申请未通过！"
								},
								keyword1: {
									value: "第三空间"
								},
								keyword2: {
									value: (apply.fee / 100).toFixed(2)
								},
								keyword3: {
									value: '微信零钱'
								},
								keyword4: {
									value: moment().tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss")
								},
								remark: {
									value: action === "PASSED" ? "感谢使用！" : apply.note
								}
							}
						})
					} else {
						console.log("用户没有关注公众号，无法发送通知")
					}
				} else {
					console.log("用户没有unionId，无法发送通知")
				}
			} catch (e) {
				console.error("发送通知遇到错误", e);
			}
	
			return {
				code: 200,
				result: {
					...apply,
					...account
				}
			}
		} catch (e) {
			console.log("审核遇到错误，事务回滚", e);
			if (transaction) {
				await transaction.rollback();
			}
			return {
				code: 500,
				msg: e.message
			}
		}
	}

	async confirmReturnRent({
		rentRecordId,
		remarks,
		pledgeRefund
	}) {
		let transaction
		try {
			transaction = await this.db.startTransaction()
			let user = await dbHelper.getById("uni-id-users", this.ctx.auth.uid)
			let rentRecord = await dbHelper.getById("t3ds-goods-rent-history", rentRecordId, transaction)
			if (!rentRecord) {
				return {
					code: 500,
					msg: "租借记录不存在"
				}
			}
			if (rentRecord.returnTime) {
				return {
					code: 500,
					msg: "已确认，无需再次确认"
				}
			}

			await dbHelper.update("t3ds-goods-rent-history", {
				_id: rentRecord._id,
				returnTime: Date.now(),
				confirmBy: user.username,
				pledgeRefund: pledgeRefund,
				remarks: remarks
			}, transaction)

			// 还原库存
			await dbHelper.update("t3ds-goods-rent", {
				_id: rentRecord.goodsId,
				stock: this.db.command.inc(rentRecord.count)
			}, transaction)

			// 更新订单状态，退押金是7即退款中，不退是5即订单完成
			await dbHelper.update("t3ds-order", {
				_id: rentRecord.orderId,
				status: pledgeRefund ? 7 : 5
			}, transaction)

			if (pledgeRefund) {
				let order = await dbHelper.getById("t3ds-order", rentRecord.orderId)
				let uniPayInstance = payUtil.getPayInstance(order.pay_type, order.platform);
				let res = await uniPayInstance.refund({
					outTradeNo: order._id,
					outRefundNo: order._id,
					totalFee: Math.round(order.payment_fee), // 订单总金额，支付宝可不填此项
					refundFee: Math.round(order.payment_fee), // 退款总金额
				})
			}

			await transaction.commit()
		} catch (e) {
			console.error(e)
			if (transaction) {
				await transaction.rollback()
			}
			return {
				code: 500,
				msg: e.message
			}
		}
	}
}
